package database;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;

import datagraphics.Visitor;

/**
 * Pregunta de opciones múltiples con 1 o más respuestas
 * correctas
 * @author Grupo 11 de Programacion Orientada a Objetos
 *
 */

public class MultipleQuestion extends Question {
	
	private String[] options;
	private Integer[] correct;
	private Integer[] usrans;
	private int correctCount;
	
	
	/**
	 * Crea una nueva instancia de MultipleQuestion
	 * @param options - Arreglo de Strings que tiene todas las opciones
	 * @param correct - Arreglo de Integer relacionado biunivocamente
	 * con options, que representa la combinación que se considera como la 
	 * respuesta válida en forma de 1's y 0's
	 * (0 - opción no correcta, 1 - opción correcta).
	 */
	
	public MultipleQuestion(String[] options, Integer[] correct) {
		super();
		this.options = options;
		this.correct = correct;
	}

	/**
	 * Devuelve true si la respuesta ingresada es correcta.
	 * La respuesta debe ser ingresada previamente con el metodo
	 * setUsrAns(Integer[] usrans).
	 * @return - Un boolean que representa si la pregunta
	 * fue contestada exitosamente. En caso de no ser contestada
	 * se retorna false
	 */
	
	public boolean validAnswer() {
	
		int i= 0;
		
		if (usrans != null) {
			for( Integer ans: usrans){
				if( !ans.equals(correct[i++])){
					return false;
				}
			}
		} else {
			return false;
		}
		
		return true;
	}

	/**
	 * Devuelve las opciones del multiple choice
	 * @return String[] - todas las opciones posibles
	 */
	
	public String[] getOptions() {
		return options;
	}

	/**
	 * Configura las opciones de la pregunta multiple choice
	 * @param options - Arreglo de String que representa las opciones
	 */
	
	public void setOptions(String[] options) {
		this.options = options;
	}

	/**
	 * Devuelve la combinación que valida como correcta
	 * a esta pregunta.
	 * @return Integer[] - Combinación correcta en forma de
	 * 1's y 0's.
	 */
	
	public Integer[] getCorrect() {
		return correct;
	}
	
	/**
	 * Configura la combinación que valida como correcta
	 * a la pregunta.
	 * @param correct - combinación correcta
	 */
	
	public void setCorrect(Integer[] correct) {
		this.correct = correct;
	}

	/**
	 * Retorna un hash de la pregunta
	 */
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + Arrays.hashCode(correct);
		result = prime * result + Arrays.hashCode(options);
		return result;
	}


	/**
	 * Compara por igualdad semantica a dos preguntas
	 * de tipo MultipleQuestion
	 * @param obj - Objeto contra el cual comparar
	 */

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		MultipleQuestion other = (MultipleQuestion) obj;
		if (!Arrays.equals(correct, other.correct))
			return false;
		if (!Arrays.equals(options, other.options))
			return false;
		return true;
	}

	/** 
	 * Recibe una instancia de un Objecto que implementa
	 * la interfaz Visitor, el cual en conjunto con este método
	 * forman el Visitor Pattern, con el cual se logra independencia
	 * en la representación gráfica en pantalla de MultipleQuestion
	 * @param visitor - instancia de un objeto que implementa Visitor
	 * y se encarga de la representación gráfica de MultipleQuestion
	 */
	
	public void accept(Visitor visitor) {
		visitor.visit(this);
		return;
	}

	/**
	 * Devuelve la respuesta elegida por el usuario
	 * @return Integer[] - Combinación elegida por el usuario
	 */
	public Integer[] getUsrAns() {
		return usrans;
	}

	/**
	 * Guarda las opciones elegidas por el usuario
	 * @param usrans - opciones elegidas
	 */
    
	public void setUsrAns(Integer[] usrans) {
		this.usrans = usrans;
	}

	/**
	 * Devuelve la cantidad correcta de respuestas
	 * @return int - cantidad respuestas correctas
	 */
	public int getCorrectCount() {
		return correctCount;
	}

	/**
	 * Establece la cantidad de respuestas correctas.
	 * @param correctCount - cantidad respuestas correctas
	 */
	public void setCorrectCount(int correctCount) {
		this.correctCount = correctCount;
	}
	
	/**
	 * Representa textualmente a MultipleQuestion
	 * completamente cualificada por nombre de clase
	 * concreta, texto de la pregunta y puntaje
	 */
	
	@Override
	public String toString() {
		String classname, qtext, scr;
		
		classname = "MultipleQuestion"; // MARK
		qtext = this.getQuestionText();
		scr = String.valueOf(this.getScore());
		
		return (classname + " - " + qtext + " - " + scr);
	}

	/**
	 * Descarga en archivo a MultipleQuestion
	 * @param fw - Instancia de FileWriter que contiene
	 * el archivo en donde debe salvarse a si misma.
	 * @throws IOException - Imposibilidad de escribir al
	 * archivo
	 */
	
	@Override
	public void saveToFile(FileWriter fw) throws IOException {
		if (correctCount > 1)
			fw.write("4");
		else
			fw.write("3");
		
		fw.write("\n");
		fw.write(String.valueOf(this.getLevel()));
		fw.write("\n");
		fw.write(String.valueOf(options.length)); // cant opciones posibles
		fw.write("\n");
		fw.write(String.valueOf(correctCount)); // posibles rtas validas
		fw.write("\n");
		fw.write(this.getQuestionText());
		fw.write("\n");
		
		for (String s : options) {
			fw.write(s);
			fw.write("\n");
		}
		
		writeAnswers(fw);
		fw.write(String.valueOf(this.getScore()));
		return;
	}
	
	/**
	 * Salva en archivo las respuestas correctas, luego de haber
	 * salvado todas las opciones
	 * @param fw - instancia de FileWriter para escribir en archivo
	 * @throws IOException - Imposibilidad de escritura
	 */
	
	private void writeAnswers (FileWriter fw) throws IOException {
		int i = 0;
		
		for (Integer ans : correct) {
			if (ans.equals(1)) {
				fw.write(options[i]);
				fw.write("\n");
			}
			i++;
		}
		
		return;
	}
}
